﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Runtime.InteropServices;
using TbcLib.OpenClient.API.Domain.Uc;
using TbcLib.OpenClient.API.Service.Uc;
using TbcLib.OpenClient.Core;
using TbcLib.OpenClient.Exception;

namespace OpenClientDemo
{
    /// <summary>
    ///   该Demo包含了SDK的调用示例：
    ///     
    ///     1. 开发者帐号设置和调用示例 参见方法 Main
    /// 
    ///     2. 单点登录url生成 参见方法 GenerateSsoUrlDemo
    /// 
    ///     /*** 部门人员组织架构 ***/
    /// 
    ///     3. 同步部门 参见方法 SyncOrganizeDemo 
    ///         
    ///     4. 同步岗位 参见方法 SyncPositionDemo 
    /// 
    ///     5. 同步人员 参见方法 SyncUserDemo 
    /// 
    /// </summary>
    class Program
    {
        private const string MyAppKey = "0F80D30BBCD94B1BA6D5053EB00A4604";
        private const string MySecret = "95329D8D97C04B819FB8B47A1C20B458";
        private const string MyBaseUrl = "heping.21tb.com";
        private const string MyCorpCode = "heping";

        /// <summary>
        ///   调用示例：
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            /*
             * 注意: 必须拥有开发者帐号才能正常使用SDK，在正式平台调用前可以先申请测试平台的开发者帐号进行调用。
             *       关于开发者帐号的申请和咨询请联系：时代光华开放平台部 邮箱: app5@21tb.com
             */

            // 设置SDK的开发者帐号信息
            ServiceManager.Init(new ServiceConfiguration()
            {
                AppKey = MyAppKey,
                Secret = MySecret,

                // 设置sdk访问的环境
                // 测试环境 yufa.21tb.com 正式环境请使用 v4.21tb.com
                // 注意：每个环境都要使用单独的AppKey和Secret，环境切换后请注意更换
                BaseUrl = MyBaseUrl,

                // 设置每次请求的超时时间 单位为毫秒，默认为30秒
                RequestTimeout = 360000,

                // 开发者模式 启用则输出详细的跟踪信息到控制台（方便进行开发者调试），Release模式请设置为false防止干扰信息
                DebugMode = false
            });

            /*    接口调用
                        
                 (1) 访问接口需要首先获取API中的Service实例
                        
                 比如：登录时需要获取 OpenLoginService
                        
                 (2) 访问接口方法时请仔细阅读方法的注释说明
                 可以直接通过源码查看，或者访问 http://v4.21tb.com/open 查看API文档
                        
                 比如：查看学员的在线学习记录
                        
                 http://v4.21tb.com/open/platform/detail.do?openMethod.id=8a8081ef498992e1014989a356500546
                        
                 调用示例如下
            */

            try
            {
                // 单点登录Url生成示例
                //GenerateSsoUrlDemo();

                // 同步部门示例
                SyncOrganizeDemo();

                // 同步岗位示例
                SyncPositionDemo();

                // 同步人员示例
                SyncUserDemo();
            }
            catch (Exception ex)
            {
                WriteLog.CreateLog(ex);
                Environment.Exit(0);
            }
        }
        /// <summary>
        ///   生成单点登录url示例
        ///   通过单点登录，可以支持指定用户通过url访问直接登录到平台
        /// </summary>
        public static void GenerateSsoUrlDemo()
        {
            /*
             * 注意: 单点登录之前必须设置公司的单点登录密钥，该密钥请确保安全保密。
             *       密钥设置请联系：时代光华开放平台部 邮箱: app5@21tb.com
             */
            // 设置登录域名 比如测试环境 yufa.21tb.com，也可以设置为自定义登录域名
            string hostUrl = MyBaseUrl;

            // 单点登录密钥
            string secret = "000000";

            // 公司编号
            string corpCode = MyCorpCode;

            // 登录用户名
            string loginName = "admin";

            // 设置returnUrl则单点登录后可以实现自动重定向到指定的页面，禁止跨域访问。不跳转可设置为null。默认为不跳转
            // 比如预览课程 http://yufa.21tb.com/els/html/coursePreview/coursepreview.preview.do?courseId=500872b6592d7fc3ab7660190d5e6dd5
            string returnUrl = null;

            // 生成单点登录url
            var ssoUrl = SsoHelper.GenerateSsoUrl(hostUrl, secret, corpCode, loginName,
                returnUrl);

            // 输出url
            Console.WriteLine(ssoUrl);
            Console.ReadKey();
        }
        /// <summary>
        ///   同步部门结构示例
        /// </summary>
        public static void SyncOrganizeDemo()
        {
            #region 原代码组织格式
            /*
                * 注意：部门组织是树形结构，部门信息由编号，名称和上级部门编号组成
                * 
                * 示例结构如下：
                *      organizeCode    organizeName    parentOrganizeCode
                *               001          根部门                     *
                *               002          子部门一                  001
                *               003          子部门二                  001
                */
            //var organizes = new List<OpenOrganize>()
            //{

            //new OpenOrganize()
            //    {
            //        OrganizeCode = "1",
            //        OrganizeName = "这是测试的主节点2",
            //        ParentCode = "*",
            //        CorpCode = MyCorpCode
            //    }
            //};
            //new OpenOrganize()
            //{
            //    OrganizeCode = "1",
            //    OrganizeName = "重庆高科技",
            //    ParentCode = "*",
            //    CorpCode = MyCorpCode
            //},
            //new OpenOrganize()
            //{
            //    OrganizeCode = "11",
            //    OrganizeName = "测试数据1",
            //    ParentCode = "1",
            //    CorpCode = MyCorpCode
            //},
            //new OpenOrganize()
            //{
            //    OrganizeCode = "012",
            //    OrganizeName = "测试数据2",
            //    ParentCode = "11",
            //    CorpCode = MyCorpCode
            //}
            //};
            //organizes.Add(new OpenOrganize()
            //{
            //    OrganizeCode = "13",
            //    OrganizeName = "测试数据3",
            //    ParentCode = "1",
            //    CorpCode = MyCorpCode
            //});

            #endregion

            #region 获取一级组织数据
            var organizes = new List<OpenOrganize>();
            string sql = "select * from organization where codesetid='UN' order by codeitemid;";
            //连接HR人员库
            using (SqlDataReader reader = SqlHelper.ExecuteReader(sql))
            {
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        organizes.Add(new OpenOrganize()
                        {
                            OrganizeCode = reader["codeitemid"].ToString(),
                            OrganizeName = reader["codeitemdesc"].ToString(),
                            ParentCode = reader["parentid"].ToString() == reader["codeitemid"].ToString() ? ((reader["parentid"].ToString() == "1" ? "*" : reader["parentid"].ToString())) : reader["parentid"].ToString(),
                            CorpCode = MyCorpCode
                        });
                    }
                }
            }
            #endregion

            #region 获取子级组织数据
            sql = "select * from organization where codesetid='UM' order by grade;";
            //连接HR人员库
            using (SqlDataReader reader = SqlHelper.ExecuteReader(sql))
            {

                while (reader.Read())
                {
                    organizes.Add(new OpenOrganize()
                    {
                        OrganizeCode = reader["codeitemid"].ToString(),
                        OrganizeName = reader["codeitemdesc"].ToString(),
                        ParentCode = reader["parentid"].ToString() == reader["codeitemid"].ToString() ? ((reader["parentid"].ToString() == "1" ? "*" : reader["parentid"].ToString())) : reader["parentid"].ToString(),
                        CorpCode = MyCorpCode
                    });
                }
            }
            #endregion
            var openOrganizeService = ServiceManager.GetServiceInstance<OpenOrganizeService>();
            Dictionary<string, string> syncResult = null;

            try
            {
                syncResult = openOrganizeService.SyncOrganizes(organizes);
            }
            catch (MethodInvokeException exception)
            {
                Console.WriteLine(exception.Message);
            }

            // 同步成功，返回同步成功的部门信息字典 [OrganizeCode], [OrganizeId]
            foreach (var result in syncResult)
            {
                Console.WriteLine(result.Key + "  " + result.Value);
            }
            //Console.ReadKey();
        }
        /// <summary>
        ///   同步岗位结构示例
        /// </summary>
        public static void SyncPositionDemo()
        {
            /*
             * 注意：每个岗位必须从属于一个岗位类别，岗位类别可有两级树形结构
             * 
             * 示例结构如下：
             *      positionCode    positionName    categoryCode    categoryName    parentCategoryCode
             *              p001       软件工程师            c001        研发序列                 null       
             *              p002       网络工程师            c001        研发序列                 null
             */
            #region 原岗位测试数据
            //var positions = new List<OpenPosition>()
            //{
            //    new OpenPosition()
            //    {
            //        PositionCode = "p001",
            //        PositionName = "软件工程师",
            //        CategoryCode = "c001",
            //        CategoryName = "研发序列",
            //        ParentCategoryCode = null,
            //        CorpCode = MyCorpCode
            //    },
            //    new OpenPosition()
            //    {
            //        PositionCode = "p002",
            //        PositionName = "网络工程师",
            //        CategoryCode = "c001",
            //        CategoryName = "研发序列",
            //        ParentCategoryCode = null,
            //        CorpCode = MyCorpCode
            //    }
            //}; 
            #endregion

            var positions = new List<OpenPosition>();

            string sql = "select codesetid,codeitemid,codeitemdesc,parentid,grade,childid from organization where codesetid = '@K';";
            //连接HR 人员库
            using (SqlDataReader reader = SqlHelper.ExecuteReader(sql))
            {
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        positions.Add(new OpenPosition()
                        {
                            //岗位编号
                            PositionCode = reader["codeitemid"].ToString(),
                            //岗位名称
                            PositionName = reader["codeitemdesc"].ToString(),
                            //岗位类别编号
                            CategoryCode = reader["grade"].ToString() == reader["codeitemid"].ToString() ? "*" : reader["grade"].ToString(),
                            //岗位类别名称
                            CategoryName = Convert.ToInt32(reader["grade"])>4?"分子公司":"公司本部",
                            //上级岗位编号
                            ParentCategoryCode = null,
                            CorpCode = MyCorpCode
                        });
                    }
                }
            }
            var positionService = ServiceManager.GetServiceInstance<OpenPositionService>();
            Dictionary<string, string> syncResult = null;
            try
            {
                syncResult = positionService.SyncPositions(positions);
            }
            catch (MethodInvokeException exception)
            {
                Console.WriteLine(exception.Message);
            }

            // 同步成功，返回同步成功的岗位信息字典 [PositionCode], [PositionId]
            foreach (var result in syncResult)
            {
                Console.WriteLine(result.Key + "  " + result.Value);
            }

            // Console.ReadKey();
        }
        /// <summary>
        ///   同步人员示例
        /// </summary>
        public static void SyncUserDemo()
        {
            #region 同步人员方法
            /*
             * 注意：同步人员方法调用前必须确保公司人员的部门和岗位结构已经同步完成，否则无法同步成功
             * 
             * 必填字段：
             *      EmployeeCode     工号 企业内唯一    
             *      UserName         姓名 可以重复 
             *      LoginName        登录用户名 登录必须，企业内唯一
             *      AccountStatus    账户状态：激活 ENABLE 冻结 FORBIDDEN
             *      OrganizeCode     部门编号 (必须已经存在) 
             *      MyCorpCode         公司编号
             *     
             * 其他选填字段：
             *      PositionCode    岗位编号 (必须已经存在)
             *      Password        登录密码 （需要MD5加密）
             *      Sex             性别 男 MAN 女 WOMAN 
             *      Birthday        出生日期
             *      OnBoarding      入职日期
             *      IdCard          身份证号码
             *      Email           电子邮箱
             *      Mobile          手机
             *      NickName        昵称
             *      DutyName        职务名称
             *      SuperiorEmployeeCode    隶属上级工号（必须已经存在）
             *      其他属性 ... （参见OpenUser类定义）
             * 
             * 如果现有的字段不能满足需求，同步时可以使用扩展字段 (目前支持10个 Ext1,Ext2 ... Ext10)
             * 
             */

            //List<OpenUser> users = new List<OpenUser>()
            //{
            //    new OpenUser()
            //    {
            //        UserName = "黎国锐",
            //        AccountStatus = "ENABLE",
            //        CorpCode = MyCorpCode,
            //        EmployeeCode = "001",
            //        Birthday = new DateTime(1990,11,11),
            //        LoginName = "liguorui",
            //        Sex = "MAN",
            //        OrganizeCode = "002",       // 子部门二（同步组织时已同步）
            //        PositionCode = "p001",      // 软件工程师（同步岗位时已同步）

            //    },
            //    new OpenUser()
            //    {
            //        UserName = "李四",
            //        AccountStatus = "ENABLE",
            //        CorpCode = MyCorpCode,
            //        EmployeeCode = "002",
            //        LoginName = "lisi",
            //        Sex = "MAN",
            //        OrganizeCode = "002",       // 子部门二（同步组织时已同步）
            //        PositionCode = "p002",      // 软件工程师（同步岗位时已同步）
            //        SuperiorEmployeeCode = "001",    // 上级为张三
            //        Ext1 = "潜力股"             // 设置扩展字段
            //    }
            //}; 
            #endregion

            var users = new List<OpenUser>();
            DateTime k = DateTime.Now;
            //and HR对应主键列=1 and HR对应主键列=1
            //string sql = @"SELECT 员工编号,员工姓名,在职标志,身份证号,出生年月,性别,培训岗位编号,培训部门编号,HR对应主键列 FROM ExployBaseFile where isnull(培训岗位编号,'')<>'' and (单位名称 not in ('资阳和平','重庆市和平','重庆医药股份有限公司','和平国根','4203') or isnull(单位名称,'')='' ) order by 员工编号 ";
            //SqlHelper.SetSqlConnection("E3sql");
            string sql = @"SELECT  E0122, E01A1, A0101, A0177, A0107,H01SU FROM UsrA01 order by H01SU";
            //连接E3人员库
            using (SqlDataReader reader = SqlHelper.ExecuteReader(sql))
            {
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        try
                        {
                            //身份证信息不是18位的则暂不同步。
                            if (reader["A0177"].ToString().Length != 18)
                            {
                                continue;
                            }
                            //没有设定部门编号的不同步
                            if (reader["E0122"].ToString().Length == 0)
                            {
                                continue;
                            }
                            //没有员工编号的不同步
                            if (reader["H01SU"].ToString().Length == 0)
                            {
                                continue;
                            }

                            users.Add(new OpenUser()
                            {
                                //员工姓名
                                UserName = reader["A0101"].ToString(),
                                //账户状态
                                AccountStatus = "ENABLE",           //reader["在职标志"].ToString() == "在职" ? "ENABLE" : "FORBDDIEN",
                                //公司编号
                                CorpCode = MyCorpCode,
                                //员工编号
                                EmployeeCode = reader["H01SU"].ToString(),
                                //员工生日出生年月
                                Birthday = Convert.ToDateTime(reader["A0177"].ToString().Substring(6, 4) + "-" + reader["A0177"].ToString().Substring(10, 2) + "-" + reader["A0177"].ToString().Substring(12, 2)),
                                //Birthday = reader["出生年月"].ToString()!=null? Convert.ToDateTime(reader["出生年月"].ToString()):DateTime.Now,
                                //登录名称
                                LoginName = reader["H01SU"].ToString(),
                                //性别
                                Sex = reader["A0107"].ToString() == "1" ? "MAN" : "WOMAN",
                                //培训部门编号
                                OrganizeCode = reader["E0122"].ToString(),
                                //培训岗位编号
                                PositionCode = reader["E01A1"].ToString()
                            });
                        }
                        catch (Exception ex)
                        {
                            //出现问题会报哪个员工的信息出错
                            throw new Exception("员工姓名:"+reader["A0101"].ToString() +"员工编号"+ reader["H01SU"].ToString()+"出现问题");

                        }
                    }
                }
            }

            var openUserService = ServiceManager.GetServiceInstance<OpenUserService>();

            Dictionary<string, string> syncResult = openUserService.SuperSyncUsers(users,
                new OpenSyncRule()
                {
                    NeedModifyPswWhenFirstLogin = true,        // 首次登录是否修改密码，默认为true
                    NeedModifyPswWhenUpdate = false            // 修改已存在员工信息时同时修改密码，默认为false
                });

            // 同步成功，返回同步成功的人员信息字典 [EmployeeCode], [UserId]
            foreach (var result in syncResult)
            {
                Console.WriteLine(result.Key + "  " + result.Value);
            }

            //Console.ReadKey();
        }
    }
}
